#define MSPROTOCOL_C
#include <stdlib.h> 
#include <stdio.h>
#include <string.h> 
#include <unistd.h>
#include <libmscommon/mscommon.h>
#include <libmscommon/msnetwork.h>
#include <libmscommon/msstring.h>
#include <libmscommon/msmd.h>
#include <libmscommon/mstime.h>
#include <libmscommon/msdenc.h>
#include <libmslog/mslog.h>
#include "msprotocol.h" 

#define FLAG "PROTOCOL"

#define enable_rtp_debug ms_false
#define CMD_RTSP(string) ( (len>ms_buflen(string)&&ms_strncmp_seq(recvbuf, string)) ||(len>0 &&ms_buflen(recvbuf)>0&& len<ms_buflen(string)&&ms_strncmp_eq(string, recvbuf,len)))

static URLProtocol *first_protocol = ms_null;
static ms_string const msptcName_string[256]={msstring_protocol};
static RTPPAYLOADTYPEContext rtpPayloadType_list[] = {	
  {RTP_PAYLOADTYPE_AUDIO_PCMU, 		"PCMU", 	"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_GSM, 		"GSM",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_G723, 		"G723",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_DVI4, 		"DVI4",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_DVI4_16000, "DVI4",	"audio", 16000, 1},
  {RTP_PAYLOADTYPE_AUDIO_LPC, 		"LPC", 		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_PCMA, 		"PCMA",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_G722, 		"G722",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_L16, 		"L16",		"audio", 44100, 2},
  {RTP_PAYLOADTYPE_AUDIO_L16_1, 	"L16",		"audio", 44100, 1},
  {RTP_PAYLOADTYPE_AUDIO_QCELP, 	"QCELP",	"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_CN, 		"CN",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_MPA, 		"MPA",		"audio", -1, -1},
  {RTP_PAYLOADTYPE_AUDIO_MPA, 		"MPA",		"audio", -1, -1},
  {RTP_PAYLOADTYPE_AUDIO_G728, 		"G728",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_AUDIO_DVI4_11025, "DVI4", 	"audio", 11025, 1},
  {RTP_PAYLOADTYPE_AUDIO_DVI4_22050, "DVI4",	"audio", 22050, 1},
  {RTP_PAYLOADTYPE_AUDIO_G729, 		"G729",		"audio", 8000, 1},
  {RTP_PAYLOADTYPE_VIDEO_CelB, 		"CelB", 	"video", 90000, -1},
  {RTP_PAYLOADTYPE_VIDEO_JPEG, 		"JPEG", 	"video", 90000, -1},
  {RTP_PAYLOADTYPE_VIDEO_nv, 		"nv",		"video", 90000, -1},
  {RTP_PAYLOADTYPE_VIDEO_H261, 		"H261", 	"video", 90000, -1},
  {RTP_PAYLOADTYPE_VIDEO_MPV, 		"MPV", 		"video", 90000, -1},
  {RTP_PAYLOADTYPE_VIDEO_MPV, 		"MPV",		"video", 90000, -1},
  {RTP_PAYLOADTYPE_DATA_MP2T, 		"MP2T", 	"data", 90000, -1},
  {RTP_PAYLOADTYPE_VIDEO_H263, 		"H263", 	"video", 90000, -1},
  {RTP_PAYLOADTYPE_CUSTOM, 			"custom", 	"video", 90000, -1},
  {RTP_PAYLOADTYPE_UNKNOW,		  	"unknow",	"data", -1, -1}
};

const ms_string const netStateCode_string[] = {
	/*1XX：通知-已收到请求，可以继续*/	
	[NETSTATE_CODE_CONTINUE]   ="Continue",
	/*2XX：成功-请求得到了成功的接收和处理*/			
	[NETSTATE_CODE_OK]="OK",
	[NETSTATE_CODE_CREATED]="Created",
	[NETSTATE_CODE_LOW_ON_STORAGE_SPACE]   ="Low on Storage Space",
	/*3XX：重定向-必须采取进一步的行动来完成请求*/		
	[NETSTATE_CODE_MULTIPLE_CHOICES]   ="Multiple Choices",
	[NETSTATE_CODE_MOVED_PERMANENTLY]="Moved Permanently",
	[NETSTATE_CODE_MOVED_TEMPORARILY]="Moved Temporarily",
	[NETSTATE_CODE_SEE_OTHER]="See Other",
	[NETSTATE_CODE_NOT_MODIFIED]="Not Modified",
	[NETSTATE_CODE_USE_PROXY]="Use Proxy",
	/*4XX：客户端错误-请求有语法错误或无法实现*/
	[NETSTATE_CODE_BAD_REQUEST]="Bad Request",
	[NETSTATE_CODE_UNAUTHORIZED]="Unauthorized",
	[NETSTATE_CODE_PAYMENT_REQUIRED] 	="Payment Required",
	[NETSTATE_CODE_FORBIDDEN]   ="Forbidden",
	[NETSTATE_CODE_NOT_FOUND]="Not Found",
	[NETSTATE_CODE_METHOD]="Method Not Allowed",
	[NETSTATE_CODE_NOT_ACCEPTABLE]="Not Acceptable",
	[NETSTATE_CODE_PROXY_AUTH_REQUIRED]    ="Proxy Authentication Required",
	[NETSTATE_CODE_REQ_TIME_OUT]="Request Time-out",
	[NETSTATE_CODE_GONE]   ="Gone",
	[NETSTATE_CODE_LENGTH_REQUIRED]="Length Required",
	[NETSTATE_CODE_PRECONDITION_FAILED]="Precondition Failed",
	[NETSTATE_CODE_REQ_ENTITY_2LARGE]="Request Entity Too Large",
	[NETSTATE_CODE_REQ_URI_2LARGE] 	="Request URI Too Large",
	[NETSTATE_CODE_UNSUPPORTED_MTYPE] 	="Unsupported Media Type",
	[NETSTATE_CODE_ERRORIO]="Error IO",
	[NETSTATE_CODE_ERROR_CONTENT]="Error Content",
	[NETSTATE_CODE_PARAM_NOT_UNDERSTOOD]   ="Parameter Not Understood",
	[NETSTATE_CODE_CONFERENCE_NOT_FOUND]   ="Conference Not Found",
	[NETSTATE_CODE_BANDWIDTH]="Not Enough Bandwidth",
	[NETSTATE_CODE_SESSION]="Session Not Found",
	[NETSTATE_CODE_STATE]  ="Method Not Valid in This State",
	[NETSTATE_CODE_INVALID_HEADER_FIELD]="Header Field Not Valid for Resource",
	[NETSTATE_CODE_INVALID_RANGE]="Invalid Range",
	[NETSTATE_CODE_RONLY_PARAMETER] 	="Parameter Is Read-Only",
	[NETSTATE_CODE_AGGREGATE]="Aggregate Operation no Allowed",
	[NETSTATE_CODE_ONLY_AGGREGATE]  ="Only Aggregate Operation Allowed",
	[NETSTATE_CODE_TRANSPORT]="Unsupported Transport",
	[NETSTATE_CODE_UNREACHABLE]="Destination Unreachable",
	/*5XX：服务端错误-服务器无法完成有效请求*/	
	[NETSTATE_CODE_INTERNAL]               		="Internal Server Error",
	[NETSTATE_CODE_NOT_IMPLEMENTED]   	="Not Implemented",
	[NETSTATE_CODE_BAD_GATEWAY]            	="Bad Gateway",
	[NETSTATE_CODE_SERVICE]                		="Service Unavailable",
	[NETSTATE_CODE_GATEWAY_TIME_OUT]   	="Gateway Time-out",
	[NETSTATE_CODE_VERSION]          			="RTSP Version not Supported",
	[NETSTATE_CODE_UNSUPPORTED_OPTION]	="Option not supported",
	//
	[NETSTATE_CODE_MAX]					="Max Statecode",
};

PTCNAMEDESContext msptcNameDes_list[]={
	{msptcName_string[msptc_file],		"File I/O operation protocol"},
	{msptcName_string[msptc_udplite],	"Use to recv or send udp data,but checksum ChecksumCoverage byte"},
	{msptcName_string[msptc_udp],		"User Datagram Protocol"},
	{msptcName_string[msptc_tcp],		"Transmission Control Protocol"},
	{msptcName_string[msptc_rtp],		"Real-time Transport Protocol"},
	{msptcName_string[msptc_msoshls_tssl],	"HTTPS Live Streaming,include a m3u8 file and many segment"},
	{msptcName_string[msptc_msoshls],	"HTTP Live Streaming,include a m3u8 file and many segment"},
	{msptcName_string[msptc_hls],		"HTTP Live Streaming,include a m3u8 file and many segment"},
	{msptcName_string[msptc_tssl],		"Transmission Control Protocol over ssl"},	
	{msptcName_string[msptc_https],		"HyperText Transfer Protocol over ssl"},
	{msptcName_string[msptc_https_vod], 	"HyperText Transfer Protocol  over ssl,used in vod"},
	{msptcName_string[msptc_dash], 		"Dynamic Adaptive Streaming over HTTP,基于HTTP的动态自适应流"},	
	{msptcName_string[msptc_http_vod], 	"HyperText Transfer Protocol,used in vod"},
	{msptcName_string[msptc_http], 		"HyperText Transfer Protocol,used in web and live"},
	{msptcName_string[msptc_rtsp], 		"Real Time Streaming Protocol"},
	{msptcName_string[msptc_rtmps], 	"Real Time Messaging Protocol over https"},
	{msptcName_string[msptc_rtmpte], 	"Real Time Messaging Protocol over http with Encryption"},
	{msptcName_string[msptc_rtmpe], 	"Real Time Messaging Protocol with Encryption"},
	{msptcName_string[msptc_rtmpt], 	"Real Time Messaging Protocol over http"},
	{msptcName_string[msptc_rtmp], 		"Real Time Messaging Protocol"},
	{msptcName_string[msptc_srt], 		"Secure Reliable Transport Protocol"},
	{msptcName_string[msptc_ws], 		"web sockect"},
	{msptcName_string[msptc_raw], 		"OP raw data"},
	{msptcName_string[msptc_none],		"Do nothing"},
	{msptcName_string[msptc_pipe],		"Use to control(read,write,remove,rename and so on) pipe"},
	{msptcName_string[msptc_fifo],		"Use to control(read,write,remove,rename and so on) fifo"},
	{msptcName_string[msptc_msav],		"Use protocol done by ffmpeg"},
	{msptcName_string[msptc_unknow],	"Unknow"}
};

static ms_void msptc_innerapi_register(URLProtocol *protocol)
{
	URLProtocol **p= &first_protocol;
    while (*p != ms_null){
		p = &(*p)->next;
	}
	*p = protocol;
    protocol->next = ms_null;
}
/*根据协议名称获取协议句柄*/
ms_void * msptc_api_matchByName(const char *name)
{
	ms_pamcheckRet(ms_null, name, "name");
	URLProtocol **p= &first_protocol;
	while (*p != ms_null){
		if( ms_strncmp_saeq(name, (*p)->nameDes->name)){
			break;
		}
		p = &(*p)->next;
	}
	return (void *)*p ;
}
/*根据协议索引获取协议句柄*/
ms_void * msptc_api_matchByPtcindex(ENUPROTOCOLIndex ptcindex)
{
	return msptc_api_matchByName((const char *)msptc_api_getPtcName(ptcindex));
}

/*根据URL获取协议句柄和URL解析信息*/
URLProtocol * msptc_api_matchAndGetUrlinfo_byUrl(const ms_u08 *url,URLInfo *pUrlInfo)
{
	ms_u08 tbuf[mscfg_maxlen_url]={0};
	ms_strcpy(tbuf, url);
	//URL解析信息
	msptc_api_urlSplit_urlinfo(pUrlInfo, tbuf);
	//获取协议句柄
	URLProtocol * purl_ptl= (URLProtocol * )msptc_api_matchByName(pUrlInfo->ptcName);//Get the right protocol
	if(ms_null==purl_ptl){
		purl_ptl=msptc_api_matchByPtcindex(msptc_msav);ms_debug( "in-use:%s",purl_ptl->nameDes->name);
	}
	return purl_ptl;
}
/*根据URL获取协议句柄*/
URLProtocol * msptc_api_matchByUrl(const ms_u08 *url)
{
	URLInfo url_info;
	return msptc_api_matchAndGetUrlinfo_byUrl(url, &url_info);
}

ENUPROTOCOLIndex msptc_api_getPtcindex(char *url,char *format,ms_bool flag_vod)
{
#define msptc_macthPtcindex(ptcindex) else if(ms_strncmp_seq(url,msptc_api_getPtcName(ptcindex))){return ptcindex;}

	bufcheck_ret(msptc_unknow, url);
	if(ms_strncmp_seq(url,msptc_api_getPtcName(msptc_file))||ms_strncmp_seq(url,"/")){
		return msptc_file;
	}
	msptc_macthPtcindex(msptc_udplite)
	msptc_macthPtcindex(msptc_udp)
	msptc_macthPtcindex(msptc_tcp)
	msptc_macthPtcindex(msptc_rtp)
	msptc_macthPtcindex(msptc_msoshls_tssl)
	msptc_macthPtcindex(msptc_msoshls)
	else if((msstr_api_isCasestr(url, "m3u8") !=0)
		||ms_strncmp_seq(url,msptc_api_getPtcName(msptc_hls))
		||(ms_null!=format &&(ms_buflen(format)>0)&& ms_strncmp_saeq(format,FFMPEG_FORMAT_HLS))){
	//非msoshls协议，且有m3u8字段、hls协议或hls封装结构
		return msptc_hls;
	}else if((msstr_api_isCasestr(url, "mpd") !=0)
		||(ms_null!=format &&(ms_buflen(format)>0)&& ms_strncmp_saeq(format,"dash"))){
	//有m3u8字段、dash封装结构
		return msptc_dash;
	}else if(ms_strncmp_seq(url,msptc_api_getPtcName(msptc_https))){
	//必须在hls后面，否则可能将HLS协议误识别为HTTPS	
		 if(ms_false!=flag_vod){
		 	return msptc_https_vod;	
		 }else{
			return msptc_https;
		 }
	}else if(ms_strncmp_seq(url,msptc_api_getPtcName(msptc_http))){
	//必须在hls后面，否则可能将HLS协议误识别为HTTP	
		 if(ms_false!=flag_vod){
		 	return msptc_http_vod;	
		 }else{
			return msptc_http;
		 }
	}
	msptc_macthPtcindex(msptc_rtsp)
	msptc_macthPtcindex(msptc_rtmps)
	msptc_macthPtcindex(msptc_rtmpte)
	msptc_macthPtcindex(msptc_rtmpe)
	msptc_macthPtcindex(msptc_rtmpt)
	msptc_macthPtcindex(msptc_rtmp)
	msptc_macthPtcindex(msptc_srt)
	msptc_macthPtcindex(msptc_ws)
	msptc_macthPtcindex(msptc_raw)
	msptc_macthPtcindex(msptc_none)
	msptc_macthPtcindex(msptc_pipe)
	msptc_macthPtcindex(msptc_fifo)
	msptc_macthPtcindex(msptc_msav)

	return msptc_unknow;
}
ms_string msptc_api_getPtcName(ENUPROTOCOLIndex ptcindex)
{
	return msptcNameDes_list[ptcindex].name;
}
RTSPDATAType msptc_api_isRtspCmd(ms_byte * recvbuf,int len)
{
	#define CMD_RTSP_RET(strCmd) if(CMD_RTSP(strCmd)){ms_debug("rtsp cmd:%s",strCmd);return RTSP_DATATYPE_ERR_CMD;}

	CMD_RTSP_RET("OPTIONS")
	else CMD_RTSP_RET("DESCRIBE")
	else CMD_RTSP_RET("ANNOUNCE")
	else CMD_RTSP_RET("SETUP")
	else CMD_RTSP_RET("PLAY")
	else CMD_RTSP_RET("RECORD")
	else CMD_RTSP_RET("GET_PARAMETER")
	else CMD_RTSP_RET("TEARDOWN")
	else CMD_RTSP_RET("PAUSE")
	return RTSP_DATATYPE_ERR_OK;
}
ms_bool msptc_api_isRtspTeardown(ms_byte * recvbuf,int len)
{
	return (CMD_RTSP("TEARDOWN")) ? ms_true : ms_false;
}

ms_u32 msptc_api_getContextLen(ms_string context,ms_u32 len)
{
	ms_u32 index=0;
	ms_bool flag_find=ms_false;
	for(index=0;index<(len-4);index++){
		if((context[index]==0x0D)&&(context[index+1]==0x0A)&&(context[index+2]==0x0D)&&(context[index+3]==0x0A)){
			flag_find=ms_true;
			break;
		}
	}
	return (flag_find==ms_true) ? (index+4) :  len;
}
ms_void msptc_api_rtpIframeDebug(IFRAMEContext *pIFrame_ctt,ms_bool flag_debug)
{
	ms_enDbg(flag_debug, "========B rtp interleaver frame====================");
	ms_enDbg(flag_debug, "-------magic:%#x",pIFrame_ctt->magic);
	ms_enDbg(flag_debug, "-------channel:%#x(0-rtp,1-rtcp)",pIFrame_ctt->channel);
	ms_enDbg(flag_debug, "-------len:%d",pIFrame_ctt->len);
	ms_enDbg(flag_debug, "========E rtp interleaver frame====================");
}
/*
buf:rtp数据包
len:rtp数据长度
flag_offset:为true时，自动空出Iframe头部空间*/
ms_s32 msptc_api_rtpIframeSet(ms_u08 *buf,ms_s32 len,ms_bool flag_offset)
{
//空出Iframe头部空间
	if(ms_true==flag_offset){
		ms_bufOffset(buf, (-RTP_IFRAME_LEN), len)
	}
//填充Iframe头部空间	
	buf[0]=RTP_IFRAME_MAGIC_NUM;
	buf[1]=RTSP_DATATYPE_RTP;
	ms_network_2b(&buf[2], len);
	return (len+RTP_IFRAME_LEN);
}

RTSPDATAType msptc_api_rtpIframeGet(IFRAMEContext *pIFrame_ctt,ms_u08 *buf,ms_s32 len)
{
	ms_memset(pIFrame_ctt, 0, sizeof(IFRAMEContext));
	ms_s32 index=0;
//查找同步字节	
	for(index=0;index<len;index++){
		if(RTP_IFRAME_MAGIC_NUM==buf[index]){
			break;
		}
	}
	if(!(index<len)){
		ms_errRet(RTSP_DATATYPE_ERR_NOMAGICNUM,"The magic num(%#x) of the rtp iframe is not found. Are they RTP (Over tcp) packets? Or data packet loss?",RTP_IFRAME_MAGIC_NUM);
	}
	pIFrame_ctt->magic		=RTP_IFRAME_MAGIC_NUM;
	pIFrame_ctt->channel	=buf[index+1];
	//此处存在BUG：RTP和RTCP的通道是由SETUP交互时协商的，此处默认为0和1有待完善；
	if((pIFrame_ctt->channel!=RTSP_DATATYPE_RTP)
		&&(pIFrame_ctt->channel!=RTSP_DATATYPE_RTCP)){
		ms_dbgRet(RTSP_DATATYPE_ERR_CHANNLE,"Unknown RTP or RTCP channel(%d). By default, channel 0 and channel 1 are used. If other channels are not supported, data will be drop",pIFrame_ctt->channel);
	}
	pIFrame_ctt->len		=ms_host_2b((&buf[index+2]));
	if(pIFrame_ctt->len  >  5000){
		ms_dbgRet(RTSP_DATATYPE_ERR_DATALEN,"The length of RTP data obtained in iframe is too large(%d byte), and an error may have occurred",pIFrame_ctt->len);
	}
	msptc_api_rtpIframeDebug( pIFrame_ctt, enable_rtp_debug);
	return pIFrame_ctt->channel;
}

RTSPDATAType msptc_api_rtpIframeDrop(MSBFIFOSIZEContext        *pBFifosize_ctt,ms_byte *recvbuf,int *pLen)
{
/*
1.完整的会话数据+RTP数据：RTP数据存入FIFO，返回会话数据；
2.异常的会话数据（无结束符）+RTP数据：RTP数据存入FIFO，返回0；
3.不完整的会话数据+RTP数据：存入整个数据到FIFO。如果FIFO中的数据足够：1.返回会话数据；2. 返回RTP数据；
3.RTP数据+完整的会话数据：存入整个数据到FIFO。如果FIFO中的数据足够：1.返回会话数据；2. 返回RTP数据；
4.RTP数据+不完整的会话数据：存入整个数据到FIFO。如果FIFO中的数据足够：1.返回会话数据；2. 返回RTP数据；
*/
	MSFIFOBLOCKContext * pBFifo_ctt=pBFifosize_ctt->pBFifo_ctt;

	//如果数据已经溢出，那么将进行数据缓存清理.BUG:清除数据可能导致数据紊乱
	pBFifosize_ctt->fifosize_left=msfifo_api_blockSizeLeft(pBFifo_ctt);;
	if( pBFifosize_ctt->fifosize_left<(*pLen)) {/* No Space left */
		msfifo_api_blockReset(pBFifo_ctt);
		pBFifosize_ctt->num_reset=msfifo_api_blockResetNum(pBFifo_ctt);
		ms_waring("The cache(%s) data overflows and will be cleaned up, which may cause data disorder.flowover,reset:%d,%d",pBFifo_ctt->name,pBFifosize_ctt->fifosize_left,(*pLen));
	}

	//如果是会话指令开头，则立马进行剥离。
	RTSPDATAType cdm_ret=msptc_api_isRtspCmd( recvbuf, (*pLen));
	if(RTSP_DATATYPE_ERR_OK!=cdm_ret){	
		ms_u32 len=4;
		ms_bufAscii("Rtsp session?", recvbuf, ((*pLen)>16)?16:(*pLen));
		ms_bool flag_findcmdend=ms_false;
		//查找会话结束符号。BUG:如果请求的会话结束错误，那么会出现无法获取结束的问题
		while((*pLen)>len){
			if((recvbuf[len-3]==0x0D)&&(recvbuf[len-2]==0x0A)&&(recvbuf[len-1]==0x0D)&&(recvbuf[len]==0x0A)){
				ms_debug("Found RTSP session terminator, session length is %d, total data length is %d",(len+1),(*pLen));
				flag_findcmdend=ms_true;
				break;
			}
			len+=1;
		}
		ms_s32 data_len=0;
		if(ms_true==flag_findcmdend&&((*pLen)>len)){
			//完整的会话，那么将只将RTP数据放入fifo。只返回会话内容
			data_len=(*pLen)-(len+1);
			(*pLen)=(len+1);
		}else{
			//如果不是完整的会话，那么将整个数据放入fifo，后续再拼接处理。不进行数据返回
			ms_waring("RTSP session terminator not found. The session data may be incomplete, and all the data will be stored in the cache for subsequent session splicing");
			data_len=(*pLen);
			(*pLen)=len=0;
		}
		if(data_len>0){
			//ms_bufHex("cmd in", &recvbuf[offset_len], data_len);
			msfifo_api_blockIn(pBFifo_ctt, &recvbuf[(*pLen)], data_len, NULL);
		}
		recvbuf[(*pLen)]=0;
		//本次返回会话指令，不进行RTP数据返回
		ms_dbgRet(cdm_ret,"RTSP session?len:%d ",(*pLen));
	}

	//如果是RTP数据，则先放入缓存；
	if((*pLen)>0){
		msfifo_api_blockIn(pBFifo_ctt, recvbuf, (*pLen), NULL);
	}

	ms_s32 sizeused=msfifo_api_blockSizeUsed(pBFifo_ctt);
	if(ms_f32==sizeused){
		(*pLen)=0;
		ms_errRet(RTSP_DATATYPE_ERR_FIFOLEN,"My God, the data length is  %d ",sizeused);
	}
	//注意：如果一个RTP数据包大于2000，那么不支持，存在问题；
	if(sizeused>mscfg_maxlen_rtp){
		//读取4个字节，可能是：1.iframe帧；2.RTSP的会话字符串的前4字节
		msfifo_api_blockOut(pBFifo_ctt, recvbuf, 4, NULL);
		//ms_bufHex("", recvbuf, 4);
		//如果是会话：1.数据加载会话；2.前面的会话拼接；
		RTSPDATAType cdm_ret=msptc_api_isRtspCmd( recvbuf,  4);
		if(RTSP_DATATYPE_ERR_OK!=cdm_ret){
			ms_bufAscii("Rtsp session?", recvbuf, 4);
			ms_bool flag_findcmdend=ms_false;
			ms_u32 len=4;
			while(sizeused>0){
				//逐个去除会话内容，直到结束；BUG:如果请求的会话结束错误，那么会出现无法获取结束的问题
				msfifo_api_blockOut(pBFifo_ctt, &recvbuf[len], 1, NULL);
				sizeused=msfifo_api_blockSizeUsed(pBFifo_ctt);
				if((recvbuf[len-3]==0x0D)&&(recvbuf[len-2]==0x0A)&&(recvbuf[len-1]==0x0D)&&(recvbuf[len]==0x0A)){
					ms_debug("Found RTSP session terminator, session length is %d, total data length is %d",(len+1),(*pLen));
					flag_findcmdend=ms_true;
					break;
				}
				len+=1;
				if(len>mscfg_maxlen_rtp){
					ms_waring("The detection data exceeds %d bytes, and the RTSP session terminator is still not found. It may not be an RTSP session",len);
					break;
				}
			}
			if(ms_true==flag_findcmdend&&((*pLen)>len)){
				//获取整个会话内容，则返回会话数据
				(*pLen)=(len+1);
				recvbuf[(*pLen)]=0;
			}else{
				//The RTSP session content end symbol was not found. Please carefully check the requested session format
				ms_waring("The RTSP session content end symbol was not found. Please carefully check the requested session format");
				(*pLen)=0;
			}
			ms_dbgRet(cdm_ret,"RTSP session?len:%d ",(*pLen));
		}else{
			//根据iframe帧获取数据内容
			IFRAMEContext rtspif_ctt;
			RTSPDATAType ret=msptc_api_rtpIframeGet(&rtspif_ctt,recvbuf,4);
			if(RTSP_DATATYPE_RTP==ret){
				msfifo_api_blockOut(pBFifo_ctt, recvbuf,rtspif_ctt.len, NULL);
				(*pLen)=rtspif_ctt.len;
			}else if(RTSP_DATATYPE_RTCP==ret){
				msfifo_api_blockOut(pBFifo_ctt, recvbuf,rtspif_ctt.len, NULL);
				(*pLen)=rtspif_ctt.len;
				return RTSP_DATATYPE_RTCP;
			}else if(RTSP_DATATYPE_ERR_NOMAGICNUM==ret){
				RTPHEADERContext rh_ctt;
				rh_ctt.flag_rtp=msptc_api_rtpHeaderGet(&rh_ctt, recvbuf, 64, ms_true);
				(*pLen)=0;
				if(rh_ctt.flag_rtp==ms_true){
					ms_errRet(RTSP_DATATYPE_ERR_IFRAME_RTP,"Failed to obtain iframe header. RTP data is detected, error code:%d",ret);
				}else{
					ms_errRet(RTSP_DATATYPE_ERR_UNKNOW,"Failed to get iframe header, error code:%d",ret);
				}
			}else{
				(*pLen)=0;
				ms_errRet(RTSP_DATATYPE_ERR_UNKNOW,"Failed to get iframe header, error code:%d",ret);
			}
		}
		//返回RTP和RTCP数据
		return RTSP_DATATYPE_RTP;
	}else{
		//数据缓存不足，暂不返回
		(*pLen)=0;
		//ms_dbgRet(RTSP_DATATYPE_ERR_FIFOLEN_TOOSMALL,"sizeused(%d) is too small",sizeused);
		return RTSP_DATATYPE_ERR_FIFOLEN_TOOSMALL;
	}
}
ms_bool msptc_api_rtpHeaderGet(RTPHEADERContext *prh_ctt,ms_u08 *buf,ms_s32 len,ms_bool debug)
{
	#define RTP_HEASER_LEN	12
	ms_memset(prh_ctt, 0, sizeof(RTPHEADERContext));
	//BYTE[0]
	prh_ctt->cc	=(buf[0]&0x0f);		//0-15
	prh_ctt->x	=(buf[0]&0x10)>>4;
	prh_ctt->p	=(buf[0]&0x20)>>5;
	prh_ctt->v	=(buf[0]&0xc0)>>6;
	 if(2!=prh_ctt->v){
	 	goto ms_check;
	 }
	if(1==prh_ctt->p
		&& ms_true==debug){
		ms_waring("The rtp has padding,but I donot complex it,maybe there is a bug" );
		ms_bufHex("rtpbuf", buf, 16);
	}
	//BYTE[1]
	prh_ctt->pt	=(buf[1]&0x7f);
	prh_ctt->m	=(buf[1]&0x80)>>7;

	prh_ctt->sequence_num	=ms_host_2b(&buf[2]);
	prh_ctt->timestamp	=(ms_host_4b(&buf[4])*1000/90);	//khz,ms  mpegts->90khz
	prh_ctt->ssrc			=ms_host_4b(&buf[8]);
	
	//CSRC:Mixer uses
#if 0	
	if(prh_ctt->cc>0){
		if( (prh_ctt->cc)  >  sizeof(prh_ctt->csrc)	
			&& ms_true==debug){
			ms_waring("The csrc arry is only (%ld),but the num of csrc data is%d ,please modify the sourcecode",sizeof(prh_ctt->csrc),prh_ctt->cc );
		}else{
			ms_u32 index=0;
			for(index=0;index<prh_ctt->cc;index++){
				prh_ctt->csrc[index]=ms_host_4b(&buf[RTP_HEASER_LEN+4*index]);
			}
		}
	}
#endif

	//HEADER EXTENSION
	if(1==prh_ctt->x){
		prh_ctt->profile_data					=ms_host_2b(&buf[12+prh_ctt->cc*4]);
		prh_ctt->lenHeader_extension			=ms_host_2b(&buf[14+prh_ctt->cc*4]);
#if 0		
		if(prh_ctt->x > ms_arrayElems(prh_ctt->header_extension)
			&& ms_true==debug){
			ms_waring("The header_extension arry is only (%ld),but the num of header_extension data is %d,please modify the sourcecode",sizeof(prh_ctt->header_extension),prh_ctt->x );
		}else{
			ms_u32 index=0;
			for(index=0;index<prh_ctt->x;index++){
				prh_ctt->header_extension[index]=ms_host_4b(&buf[RTP_HEASER_LEN+(prh_ctt->cc*4)+4+4*index]);
			}
		}
#endif
		prh_ctt->lenHeader=RTP_HEASER_LEN+(prh_ctt->cc*4)+4+(prh_ctt->lenHeader_extension*4);
	}else{
		prh_ctt->lenHeader=RTP_HEASER_LEN+(prh_ctt->cc*4);
	}
	if(RTP_PAYLOADTYPE_AUDIO_MPA==prh_ctt->pt){
		prh_ctt->lenHeader+=4;
	}

ms_check:
	if((2!=prh_ctt->v)
		||ms_moreThan(prh_ctt->lenHeader, len)
		||ms_moreThan(prh_ctt->lenHeader, 64)
		||ms_lessThan(prh_ctt->lenHeader, 12)
	){
	#if 0	
		ms_waring("rtp version isnot 2---(%d),"
			"May the pkt is not a rtppkt,because of the too long header_total_len:%d ,data len %d---(%d)",
			(2!=prh_ctt->v) ,
			prh_ctt->lenHeader,len,
			(prh_ctt->lenHeader>64)	);
	#endif	
		return ms_false;
	}else{
		return ms_true;
	}
	
}
ms_s32 msptc_api_rtpHeaderSet(RTPHEADERContext ms_in *prh_ctt,ms_u08 payload,ms_s08 ms_out *buf ,ms_s32 ms_out size,ms_bool is_offset)
{
	prh_ctt->flag_rtp=ms_true;
	if(ms_true!=prh_ctt->flag_init){
		prh_ctt->lenHeader=RTP_HEASER_LEN;
		//BYTE[0]
		prh_ctt->cc	=0;
		prh_ctt->x	=0;
		prh_ctt->p	=0;
		prh_ctt->v	=0x2;
		//BYTE[1]
		prh_ctt->pt	=payload;	//33-MP2T,14-MPA
		prh_ctt->m	=0;
		prh_ctt->sequence_num	=0;
		prh_ctt->timestamp_base	=(ms_u32)mstime_api_us()*90/1000;	//khz,ms  mpegts->90khz
		prh_ctt->ssrc		 		=(ms_u32)mstime_api_us();
		//CSRC
		//HEADER EXTENSION
		prh_ctt->lenHeader=RTP_HEASER_LEN;
		prh_ctt->flag_init=ms_true;
	}else{
		prh_ctt->sequence_num	+=1;
		prh_ctt->timestamp=((ms_u32)mstime_api_us()*90/1000-prh_ctt->timestamp_base);	//khz,ms  mpegts->90khz
	}
	
	if(ms_true==is_offset){
		if(RTP_PAYLOADTYPE_AUDIO_MPA==prh_ctt->pt){
			ms_bufOffset(buf, -(RTP_HEASER_LEN+4), size);
		}else{
			ms_bufOffset(buf, -RTP_HEASER_LEN, size);
		}
	}
	//BYTE[0]
	buf[0]=(prh_ctt->v<<6)|(prh_ctt->p<<5)|(prh_ctt->x<<4)|(prh_ctt->cc);
	//BYTE[1]
	buf[1]=(prh_ctt->m<<7)|(prh_ctt->pt);
	//BYTE[2:3]
	ms_network_2b(&buf[2], prh_ctt->sequence_num);
	//BYTE[4:7]
	ms_network_4b(&buf[4], prh_ctt->timestamp);
	//BYTE[8:11]
	ms_network_4b(&buf[8], prh_ctt->ssrc);
	
	if(RTP_PAYLOADTYPE_AUDIO_MPA==prh_ctt->pt){
		ms_network_4b(&buf[12], 0x0);
	}
	return (RTP_PAYLOADTYPE_AUDIO_MPA==prh_ctt->pt)  ?  (size+RTP_HEASER_LEN+4)  :   (size+RTP_HEASER_LEN);
}
ms_void msptc_api_rtpHeaderDebug(RTPHEADERContext *prh_ctt,ms_bool enable_debug)
{
	ms_enDbg(enable_debug, "========B rtp===========header_total_len:%d", prh_ctt->lenHeader);
	
	ms_enDbg(enable_debug, "num of csrc:%d", prh_ctt->cc);
	ms_enDbg(enable_debug, "header extension:%d", prh_ctt->x);
	ms_enDbg(enable_debug, "padding:%d", prh_ctt->p);
	ms_enDbg(enable_debug, "version:%d", prh_ctt->v);
	
	ms_enDbg(enable_debug, "playload:%d", prh_ctt->pt);
	ms_enDbg(enable_debug, "m:%d", prh_ctt->m);
	
	ms_enDbg(enable_debug, "sequence number:%d", prh_ctt->sequence_num);
	ms_enDbg(enable_debug, "timestamp:%u", prh_ctt->timestamp);
	ms_enDbg(enable_debug, "ssrc:%u", prh_ctt->ssrc);
#if 0	
	if(prh_ctt->cc>0){
		if( (prh_ctt->cc)  >  sizeof(prh_ctt->csrc)	){
			ms_waring("The csrc arry is only (%ld),but the num of csrc data is%d ,please modify the sourcecode",sizeof(prh_ctt->csrc),prh_ctt->cc );
		}else{
			ms_u32 index=0;
			for(index=0;index<prh_ctt->cc;index++){
				ms_enDbg(enable_debug, "csrc%d:%u", index,prh_ctt->csrc[index]);
			}
		}
	}
#endif
	ms_enDbg(enable_debug, "========E rtp============================");
}

ms_void msptc_api_rtpHeaderDebug2(RTPContext * prtp_ctt,ms_string desinfo,ms_u08 *buf,ms_s32 len,ms_bool enable_debug)
{
	RTPContext rtp_ctt;
	if(prtp_ctt==ms_null){
		ms_stru0(&rtp_ctt, RTPContext);
		prtp_ctt=&rtp_ctt;
	}
	
	RTPHEADERContext *prh_ctt=&prtp_ctt->rh_ctt;
	msptc_api_rtpHeaderGet(prh_ctt,buf,len,ms_true);
	msptc_api_rtpHeaderDebug(prh_ctt,enable_debug);	
	if( (0!=prtp_ctt->snum_pre)
		&&ms_noLess(prtp_ctt->snum_pre, prh_ctt->sequence_num)
		&&ms_lessThan((prtp_ctt->snum_pre-prh_ctt->sequence_num),100) 	){
		ms_waring("[%s]--%u--%u,error sequence_num_pre(sequence_num_pre>sequence_num)", 
			desinfo,
			prtp_ctt->snum_pre, 
			prh_ctt->sequence_num);
			return;
	}
	if( (0!=prtp_ctt->snum_pre)
		&&ms_lessThan(prtp_ctt->snum_pre, prh_ctt->sequence_num)
		&&ms_noLess((prh_ctt->sequence_num-prtp_ctt->snum_pre), 30000)){
		ms_waring("[%s]--%u--%u,error sequence_num_pre(sequence_num_pre<sequence_num too much)",
			desinfo,
			prtp_ctt->snum_pre, 
			prh_ctt->sequence_num);
		return;
	}
	prtp_ctt->snum_pre=prh_ctt->sequence_num;
	//ms_enBufHex(enable_debug, "data", &buf[prh_ctt.header_total_len], (len-prh_ctt.header_total_len));
}
ms_void msptc_api_rtpHeaderDebug3(ms_u08 *buf,ms_s32 len,ms_bool enable_debug)
{
	ROTHEADERContext rtpovertcp_header_ctt;
	ms_memset(&rtpovertcp_header_ctt, 0, sizeof(ROTHEADERContext));

	IFRAMEContext *prtspif_ctt=&rtpovertcp_header_ctt.ifCtt;
	RTPHEADERContext *prh_ctt=&rtpovertcp_header_ctt.rhCtt;
	if(!(msptc_api_rtpIframeGet(prtspif_ctt,buf, len)<0)){
		msptc_api_rtpHeaderGet(prh_ctt,&buf[4],(len-4),ms_true);
		rtpovertcp_header_ctt.payload_len=prtspif_ctt->len-prh_ctt->lenHeader;
		
		msptc_api_rtpIframeDebug( prtspif_ctt, enable_debug);
		msptc_api_rtpHeaderDebug(prh_ctt,enable_debug);	
		ms_enDbg(enable_debug, "payload_len:%d\r\n", rtpovertcp_header_ctt.payload_len);
	}
}
ms_bool msptc_api_rtpHeader_checkSequence(RTPContext * prtp_ctt,ms_string desinfo,ms_u08 *buf,ms_s32 len)
{
	ms_pamcheckRet(ms_false, prtp_ctt, "prtp_ctt");
	RTPHEADERContext *prh_ctt=&prtp_ctt->rh_ctt;
	msptc_api_rtpHeaderGet(prh_ctt,buf,len,ms_true);
	msptc_api_rtpHeaderDebug(prh_ctt,ms_true);	
	ms_debug("[%s]--%u--%u,sequence_num_pre(sequence_num_pre>sequence_num)", 
		desinfo,
		prtp_ctt->snum_pre, 
		prh_ctt->sequence_num);
	if( (0!=prtp_ctt->snum_pre)
		&&ms_noLess(prtp_ctt->snum_pre, prh_ctt->sequence_num)
		&&ms_lessThan((prtp_ctt->snum_pre-prh_ctt->sequence_num),100) 	){
		ms_waring("[%s]--%u--%u,error sequence_num_pre(sequence_num_pre>sequence_num)", 
			desinfo,
			prtp_ctt->snum_pre, 
			prh_ctt->sequence_num);
			msptc_api_rtpHeaderDebug(prh_ctt,ms_true);	
			return ms_false;
	}
	if( (0!=prtp_ctt->snum_pre)
		&&ms_lessThan(prtp_ctt->snum_pre, prh_ctt->sequence_num)
		&&ms_noLess((prh_ctt->sequence_num-prtp_ctt->snum_pre), 30000)){
		ms_waring("[%s]--%u--%u,error sequence_num_pre(sequence_num_pre<sequence_num too much)",
			desinfo,
			prtp_ctt->snum_pre, 
			prh_ctt->sequence_num);
		msptc_api_rtpHeaderDebug(prh_ctt,ms_true);	
		return ms_false;
	}
	prtp_ctt->snum_pre=prh_ctt->sequence_num;
	return ms_true;
}
ms_bool msptc_api_rtpCheck(RTPHEADERContext *prh_ctt,ms_u08 *buf, int len ,ms_bool flag_checkiframe)
{
	/*BEGAIN:new pkt*/
	RTPHEADERContext rtpheader_ctt;
	if(prh_ctt==ms_null){
		prh_ctt=&rtpheader_ctt;
	}

	ms_u08 *pdatabuf=buf;
	int len_data=len;
	IFRAMEContext rtspif_ctt;
	if(ms_true==flag_checkiframe){
		if(!(msptc_api_rtpIframeGet(&rtspif_ctt, pdatabuf,len_data)<0)){
			pdatabuf=&buf[RTP_IFRAME_LEN];
			len_data=len-RTP_IFRAME_LEN;
		}else{
			prh_ctt->flag_rtp=ms_false;
			return prh_ctt->flag_rtp;
		}
	}
	prh_ctt->flag_rtp=msptc_api_rtpHeaderGet(prh_ctt,pdatabuf,len_data,ms_true);
	return prh_ctt->flag_rtp; 
}
ms_s32 msptc_api_rtpFifoout(RTPContext * prtp_ctt,ms_u08 **ppbuf, int *len )
{
	if(ms_null==prtp_ctt->pFifoPkt_ctt){
		return -1;
	}
	ms_bool flag_must=ms_false;
ms_tryagain:
	if((MAXNUM_FIFO_RTPPKT/2)<prtp_ctt->fifoPtk_num){
		prtp_ctt->snum_except+=1;
		flag_must=ms_true;
	}
	ms_s32 index=0;
	for(index=0;index<MAXNUM_FIFO_RTPPKT;index++){
		RTPPKTFIFOContext *prtppktfifo_ctt=&prtp_ctt->pFifoPkt_ctt[index];
		if(ms_true==prtppktfifo_ctt->flag_use &&prtp_ctt->snum_except==prtppktfifo_ctt->sequence_num){
			(*len)=prtppktfifo_ctt->sequence_num;
			(*len)=prtppktfifo_ctt->data_len;
			ms_memcpy((*ppbuf),prtppktfifo_ctt->data,prtppktfifo_ctt->data_len);
			prtp_ctt->fifoPtk_num-=1;
			ms_buf0(prtppktfifo_ctt->data);
			prtppktfifo_ctt->flag_use=ms_false;
			//ms_debug("get %d sequence_num(%d) to fifo%d---rtptfifo_ptknum:%d",prtppktfifo_ctt->data_len, prtppktfifo_ctt->sequence_num,index,prtp_ctt->rtptfifo_ptknum);
			return index;
		}
	}
	if(ms_true==flag_must){
		goto ms_tryagain;
	}
	return -1;
}
ms_void msptc_api_rtpFifoin(RTPContext * prtp_ctt,ms_u08 *buf, int *len ,ms_u16 sequence_num)
{
	if(ms_null==prtp_ctt->pFifoPkt_ctt){
		return ;
	}
	ms_s32 index=0;
	for(index=0;index<MAXNUM_FIFO_RTPPKT;index++){
		RTPPKTFIFOContext *prtppktfifo_ctt=&prtp_ctt->pFifoPkt_ctt[index];
		if(ms_false==prtppktfifo_ctt->flag_use){
			prtppktfifo_ctt->sequence_num=sequence_num;
			prtppktfifo_ctt->data_len=(*len);
			ms_memcpy(prtppktfifo_ctt->data, buf,prtppktfifo_ctt->data_len);
			prtppktfifo_ctt->flag_use=ms_true;
			prtp_ctt->fifoPtk_num+=1;
			//ms_debug("put %d sequence_num(%d) to fifo%d------rtptfifo_ptknum:%d",prtppktfifo_ctt->data_len, prtppktfifo_ctt->sequence_num,index,prtp_ctt->rtptfifo_ptknum);
			break;
		}
	}
}
void msptc_api_rtpDec(RTPContext * prtp_ctt,ms_u08 *buf, int *len ,ms_bool flag_checkiframe)
{	
	/*BEGAIN:new pkt*/
	RTPContext rtp_ctt;
	if(prtp_ctt==ms_null){
		prtp_ctt=&rtp_ctt;
	}
	RTPHEADERContext *prh_ctt=&prtp_ctt->rh_ctt;
ms_recheck:	
	if(ms_true==msptc_api_rtpCheck(prh_ctt,buf, (*len ),flag_checkiframe)){
		//ms_debug("---------------------------------------------sequence_num:%u,len:%d",prh_ctt->sequence_num,(*len));
		if(ms_true==prtp_ctt->flag_checkSNum){
			if((0!=prtp_ctt->snum_except)
				&&(prtp_ctt->snum_except!=prh_ctt->sequence_num)
			){
				/*
					if(sequence_num_need  >  sequence_num)
						30					20			drop  old pkt
						65536				1			nodrop
					else if(sequence_num_need  <  sequence_num)
						30					50			nodrop
						1					65536		drop  old pkt
					else if sequence_num_need  ==  sequence_num)
						30					30			nodrop
					else
						rtp fifoin

				*/
				if( ms_moreThan(prtp_ctt->snum_except, prh_ctt->sequence_num)
					&&ms_lessThan((prtp_ctt->snum_except-prh_ctt->sequence_num),100) 	){
					(*len)=0;
					ms_debug("drop %u--%u,error sequence_num(sequence_num_need>sequence_num && sequence_num_need<(sequence_num+100))",
						prtp_ctt->snum_except, prh_ctt->sequence_num);
					return;
				}else if( ms_lessThan(prtp_ctt->snum_except, prh_ctt->sequence_num)
					&&ms_noLess((prh_ctt->sequence_num-prtp_ctt->snum_except), 30000)){
					(*len)=0;
					ms_debug("drop %u--%u,error sequence_num(sequence_num_need<sequence_num && (sequence_num_need+30000)<sequence_num)",
						prtp_ctt->snum_except, prh_ctt->sequence_num);
					return;
				}else if(prtp_ctt->snum_except==prh_ctt->sequence_num) {

				}else{
					if(ms_null!=prtp_ctt->pFifoPkt_ctt){
						//rtp(over udp) fifo:to correct sequence num
						msptc_api_rtpFifoin(prtp_ctt,  buf, len,  prh_ctt->sequence_num);
						(*len)=0;
						ms_debug("%u--%u,error sequence_num(sequence_num_need<sequence_num),rtptfifo_ptknum:%d",
							prtp_ctt->snum_except, prh_ctt->sequence_num,prtp_ctt->fifoPtk_num);
						return;
					}
				}
			}
		}
		prtp_ctt->snum_pre=prh_ctt->sequence_num;
		prtp_ctt->snum_except=prh_ctt->sequence_num+1;
		(*len)-=prh_ctt->lenHeader;
		ms_bufOffset(buf, prh_ctt->lenHeader, (*len));
	}
}

ms_bool msptc_api_parseRequest(char *inbuf,WEBREQUESTContext *prequest_ctt,ms_string str_parase_out)
{
#define error_info_out(fmt,arg...) \
	ms_sprintfs(error_info, fmt,##arg); \
	if(ms_null!=str_parase_out){ms_strcpy(str_parase_out, error_info);}ms_error("%s",error_info);
	
	memset(prequest_ctt,0,sizeof(WEBREQUESTContext));
	ms_byte error_info[256]={0};
	ms_bool flag_lineend_unusual=ms_false;
	if(ms_false==msstr_api_isCasestr(inbuf, "Content-Length")){
		ms_s32 num_ret=mslog_api_strCasestrNum(inbuf, "\r\n\r\n", ms_false,ms_true);
		ms_s32 num_ret_1=mslog_api_strCasestrNum(inbuf, "\r\n\r\n\r\n", ms_false,ms_true);
		ms_s32 num_ret_2=mslog_api_strCasestrNum(inbuf, "\r\n\r\n\r\n\r\n", ms_false,ms_true);
		if(num_ret>1&&
			!(1==num_ret_1&&2==num_ret)&&
			!(1==num_ret_2&&3==num_ret)){
			flag_lineend_unusual=ms_true;
			error_info_out("Oh,has %d * \\r\\n\\r\\n",num_ret);
		}
	}
//TEARDOWN rtsp://127.0.0.1:8010/designated_ch1 RTSP/1.0   
//GET  /ch1.ts  HTTP/1.0
	char *p =inbuf;	
	ms_more("%s",inbuf);
	msstr_api_getWord(prequest_ctt->method, sizeof(prequest_ctt->method), (const char **)&p);	
	ms_more("1.%s ",prequest_ctt->method);
	msstr_api_getWord(prequest_ctt->url, sizeof(prequest_ctt->url), (const char **)&p);
	ms_more("2.%s",prequest_ctt->url);
	msstr_api_getWord(prequest_ctt->protocol, sizeof(prequest_ctt->protocol), (const char **)&p);
	ms_more("3.%s",prequest_ctt->protocol);
	char tbuf[5120]={0};

	prequest_ctt->falg_hascontent=ms_false;
	ms_bool flag_end=ms_false;
	ms_bool flag_context_error=ms_false;

	if(0==ms_buflen(prequest_ctt->method)){
		flag_context_error=ms_true;
		error_info_out("no method");
	}else{
		if(msstr_api_isCasestr(prequest_ctt->protocol, "HTTP") ){
			if(!msstr_api_isCasestr(METHOD_ALLOWED_HTTP, prequest_ctt->method) ){
				flag_context_error=ms_true;
				error_info_out("Method not allowed");
			}
		}else if (msstr_api_isCasestr(prequest_ctt->protocol, "RTSP") ){
			if(!msstr_api_isCasestr(METHOD_ALLOWED_RTSP, prequest_ctt->method) ){
				flag_context_error=ms_true;
				error_info_out("Method not allowed");
			}
		}
	}
	if(0==ms_buflen(prequest_ctt->url)){
		flag_context_error=ms_true;
		error_info_out("no url");
	}
	if(0==ms_buflen(prequest_ctt->protocol)){
		flag_context_error=ms_true;
		error_info_out("no protocol");
	}
	if(msstr_api_isCasestr(prequest_ctt->protocol, "HTTP") !=0){
		ms_byte temp_url[5120];
		ms_strcpy(temp_url,prequest_ctt->url);
		ms_string str_array_item[16];
		ms_s32 num_param=msstr_api_split(temp_url, "?", str_array_item);
		ms_s32 item_index=0;
		if(num_param>1){
			ms_strcpy(prequest_ctt->extern_data.http_rd.webhost_info.url_param,str_array_item[1]);
		}

		prequest_ctt->ptl_index=msptc_http;
		HTTPREQUESTData *phttp_rd=&prequest_ctt->extern_data.http_rd;
		while(0!=*p){
			ms_memset(tbuf,0,sizeof(tbuf));
			if(ms_true==prequest_ctt->falg_hascontent){
				msstr_api_getLine3(tbuf, sizeof(tbuf), (const char **)&p);
				//ms_debug("1-----------tbuf:%s",tbuf);
			}else{
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				//ms_debug("2-----------tbuf:%s",tbuf);
			}
			if(ms_true==prequest_ctt->falg_hascontent){
				if(ms_false==flag_end){
					if(ms_strncmp_saeq(tbuf, "\r\n")
						||ms_strncmp_saeq(tbuf, "\r")){
						flag_end=ms_true;
					}
				}else{
					if(ms_buflen(tbuf)>0){
						ms_byte tbuftmp[5120];
						ms_strcats(tbuftmp,prequest_ctt->content,"%s",tbuf);
					}
				}
				//ms_debug("content(%d):\r\n%s",(ms_s32)ms_buflen(prequest_ctt->content),prequest_ctt->content);
			}else if(msstr_api_isCasestr(tbuf, "Host:") !=0){
			//获取HOST的数值
				WEBHOSTInfo *pwebhost_info=&prequest_ctt->extern_data.http_rd.webhost_info;
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(phttp_rd->webhost_info.server_host,"%s",tbuf);
				ms_byte url[1024]={0};
				ms_sprintfs(url, "http://%s", phttp_rd->webhost_info.server_host);
				ms_more("url:%s",url);
				ms_more("server_host:%s",phttp_rd->webhost_info.server_host);
			//将HOST分解为IP和PORT
				URLInfo url_info;
				ms_memset0(&url_info, ms_bufsize(URLInfo));
				msptc_api_urlSplit_urlinfo(&url_info, url);
				phttp_rd->webhost_info.flag_ipv6=url_info.flag_ipv6;
				ms_sprintfs(phttp_rd->webhost_info.server_port, "%d", url_info.port);
				if(phttp_rd->webhost_info.flag_ipv6){
					ms_sprintfs(phttp_rd->webhost_info.server_ip, "[%s]",url_info.hostname);
				}else{
					ms_strcpy(phttp_rd->webhost_info.server_ip, url_info.hostname);
				}
				ms_more("server_ip:%s",phttp_rd->webhost_info.server_ip);
				ms_more("server_port:%s",phttp_rd->webhost_info.server_port);
			}else if(msstr_api_isCasestr(tbuf, "X-Real-IP:") !=0){
				msstr_api_getLine2(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->xReal_ip,"%s",tbuf);
				ms_verbose("X-Real-IP:%s",prequest_ctt->xReal_ip);
			}else if(msstr_api_isCasestr(tbuf, "User-Agent:") !=0){
				msstr_api_getLine2(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->user_agent,"%s",tbuf);
				ms_verbose("User-Agent:%s",prequest_ctt->user_agent);
			}else if(msstr_api_isCasestr(tbuf, "Content-Type:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->content_type,"%s",tbuf);
				ms_verbose("Content-Type:%s",prequest_ctt->content_type);
			}else if(msstr_api_isCasestr(tbuf, "Content-Length:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				prequest_ctt->content_len=ms_atoi(tbuf);
				ms_verbose("Content-Length=%d",prequest_ctt->content_len);
				prequest_ctt->falg_hascontent=ms_true;
				ms_buf0(prequest_ctt->content);
			}else if(msstr_api_isCasestr(tbuf, "Connection:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->connection,"%s",tbuf);
				ms_verbose("Connection=%s",prequest_ctt->connection);
			}
//存在Sec-WebSocket-*字段，则判断为websockect协议		
			else if(msstr_api_isCasestr(tbuf, "Upgrade: websocket") !=0){
				prequest_ctt->ptl_index=msptc_ws;
			}else if(msstr_api_isCasestr(tbuf, "Sec-WebSocket-Key:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->sec_webSocket_key,"%s",tbuf);
				ms_verbose("Sec-WebSocket-Key=%s",prequest_ctt->sec_webSocket_key);
				prequest_ctt->ptl_index=msptc_ws;
			}else if(msstr_api_isCasestr(tbuf, "Sec-WebSocket-Version:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->sec_webSocket_version,"%s",tbuf);
				ms_verbose("Sec-WebSocket-Version=%s",prequest_ctt->sec_webSocket_version);
				prequest_ctt->ptl_index=msptc_ws;
			}else if(msstr_api_isCasestr(tbuf, "Sec-WebSocket-Accept:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->sec_webSocket_accept,"%s",tbuf);
				ms_verbose("Sec-WebSocket-Accept=%s",prequest_ctt->sec_webSocket_accept);
				prequest_ctt->ptl_index=msptc_ws;
			}
		}
	}else  if(msstr_api_isCasestr(prequest_ctt->protocol, "RTSP") !=0){ 
		prequest_ctt->ptl_index=msptc_rtsp;
		RTSPREQUESTData *prtsp_rd=&prequest_ctt->extern_data.rtsp_rd;
		while(0!=*p){
			memset(tbuf,0,sizeof(tbuf));
			if(ms_true==prequest_ctt->falg_hascontent){
				msstr_api_getLine3(tbuf, sizeof(tbuf), (const char **)&p);
				//ms_debug("1-----------tbuf:%s",tbuf);
			}else{
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				//ms_debug("2-----------tbuf:%s",tbuf);
			}
			if(ms_true==prequest_ctt->falg_hascontent){
				if(ms_false==flag_end){
					if(ms_strncmp_saeq(tbuf, "\r\n")
						||ms_strncmp_saeq(tbuf, "\r")){
						flag_end=ms_true;
					}
				}else{
					if(ms_buflen(tbuf)>0){
						ms_byte tbuftmp[5120];
						ms_strcats(tbuftmp,prequest_ctt->content,"%s",tbuf);
					}
				}
				//ms_debug("content(%d):\r\n%s",(ms_s32)ms_buflen(prequest_ctt->content),prequest_ctt->content);
			}else if(msstr_api_isCasestr(tbuf, "CSeq") !=0){
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prtsp_rd->CSeq,"%s",tbuf);
			}else if(msstr_api_isCasestr(tbuf, "Transport") !=0){
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prtsp_rd->Transport,"%s",tbuf);
			}else if(msstr_api_isCasestr(tbuf, "Range") !=0){
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prtsp_rd->Range,"%s",tbuf);
			}else if(msstr_api_isCasestr(tbuf, "Session") !=0){
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prtsp_rd->Session,"%s",tbuf);
			}else if(msstr_api_isCasestr(tbuf, "pscAccept") !=0){
				msstr_api_getWord(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prtsp_rd->pscAccept,"%s",tbuf);
			}else	 if(msstr_api_isCasestr(tbuf, "User-Agent:") !=0){
				msstr_api_getLine2(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->user_agent,"%s",tbuf);
				ms_verbose("User-Agent:%s",prequest_ctt->user_agent);
			}else	 if(msstr_api_isCasestr(tbuf, "Content-Type:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->content_type,"%s",tbuf);
				ms_verbose("Content-Type:%s",prequest_ctt->content_type);
			}else	 if(msstr_api_isCasestr(tbuf, "Content-Length:") !=0){
				msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
				ms_sprintfs(prequest_ctt->user_agent,"%s",tbuf);
				prequest_ctt->content_len=ms_atoi(tbuf);
				ms_verbose("Content-Length=%d",prequest_ctt->content_len);
				prequest_ctt->falg_hascontent=ms_true;
				ms_buf0(prequest_ctt->content);
			}
		}
		ms_more("CSeq:%s",prtsp_rd->CSeq);
		ms_more("Transport:%s",prtsp_rd->Transport);
		ms_more("Range:%s",prtsp_rd->Range);
		ms_more("Session:%s",prtsp_rd->Session);
		ms_more("pscAccept:%s",prtsp_rd->pscAccept);	
		ms_more("user_agent:%s",prequest_ctt->user_agent);	
		if(0==ms_buflen(prtsp_rd->CSeq)){
			error_info_out("no CSeq");
			flag_context_error=ms_true;
		}
	}else{
		prequest_ctt->ptl_index=msptc_unknow;
		error_info_out("Error protocol:%s", prequest_ctt->protocol);
		flag_context_error=ms_true;
	}

	if((ms_true==prequest_ctt->falg_hascontent)
		&&(prequest_ctt->content_len!=ms_buflen(prequest_ctt->content))){
		if(ms_noLess(ms_buflen(prequest_ctt->content), ms_bufsize(prequest_ctt->content))){
			ms_debug( "Content len error:content_len(%d) is out of range %ld",prequest_ctt->content_len,ms_bufsize(prequest_ctt->content));
		}else{
			if(prequest_ctt->content_len>ms_buflen(prequest_ctt->content)){
				ms_waring("content_len(%d)  != ms_buflen(content)(%d)", prequest_ctt->content_len,(ms_s32)ms_buflen(prequest_ctt->content));
			}else{
				ms_debug("content_len(%d)  != ms_buflen(content)(%d)", prequest_ctt->content_len,(ms_s32)ms_buflen(prequest_ctt->content));
			}
			//ms_bufAscii("content", prequest_ctt->content,ms_buflen(prequest_ctt->content));
			//ms_bufHex("content", prequest_ctt->content,ms_buflen(prequest_ctt->content));
		}
	}

	ms_bool  retend=ms_true;
	if(((ms_true==flag_lineend_unusual)&&(ms_false==msstr_api_isCasestr(prequest_ctt->user_agent, "EBS")))
		||(ms_true==flag_context_error)
	){
		retend=ms_false;
	}
	return retend;
}

ms_s08 msptc_api_init(void)
{
#ifdef CONFIG_MSPROTOCOL_SRT
	extern void mssrt_init();
	mssrt_init();
#endif
	msnet_api_init();
}
void msptc_api_deinit(void)
{
	//srt_cleanup();
#ifdef CONFIG_MSPROTOCOL_SRT
	extern void mssrt_deinit();
	mssrt_deinit();
#endif
	msnet_api_deinit();
}
void msptc_api_register(void)
{
#define REGISTER_PROTOCOL(x) { \
    extern URLProtocol ffurl_##x##_protocol; \
    msptc_innerapi_register(&ffurl_##x##_protocol); \
    ms_verbose("*  %s" ,ffurl_##x##_protocol.nameDes->name); }
	ms_verbose("===PROTOCOL *  Table===");	
	REGISTER_PROTOCOL(file);
	REGISTER_PROTOCOL(udplite);
	REGISTER_PROTOCOL(udp);	
	REGISTER_PROTOCOL(tcp);	
	REGISTER_PROTOCOL(rtp);
	REGISTER_PROTOCOL(msoshls_tssl);
	REGISTER_PROTOCOL(msoshls);
#if defined CONFIG_MSPROTOCOL_TSSL 
	REGISTER_PROTOCOL(tssl);	
#endif
	REGISTER_PROTOCOL(https);
	REGISTER_PROTOCOL(http);
	REGISTER_PROTOCOL(rtsp);
#ifdef CONFIG_MSPROTOCOL_LIBRTMP
	REGISTER_PROTOCOL (rtmps);
	REGISTER_PROTOCOL (rtmpte);
	REGISTER_PROTOCOL (rtmpe);
	REGISTER_PROTOCOL (rtmpt);
	REGISTER_PROTOCOL (rtmp);
#endif
#ifdef CONFIG_MSPROTOCOL_SRT
	REGISTER_PROTOCOL(srt);
#endif
	REGISTER_PROTOCOL(ws);
	REGISTER_PROTOCOL(raw); 
	REGISTER_PROTOCOL(pipe);
	REGISTER_PROTOCOL(none);		//use to do test out
#ifdef CONFIG_MSPROTOCOL_MSAV
	REGISTER_PROTOCOL(msav);
#endif
	ms_verbose("========================");	
}

ms_s32 msptc_api_io(URLContext *pcilent_ctt, ms_pu08 buf, ms_s32 len,ms_s32 (*url_io)(URLContext *, ms_pu08 , ms_s32 ))
{
	ms_s32 io_len=0;
	ms_s32 total_len=len;
	while(total_len>0){
		io_len=url_io(pcilent_ctt,buf,total_len);
		if(io_len>0){
			total_len-=io_len;
		}else{
			break;
		}
	}
	return	(len- total_len);
}
ms_bool msptc_api_statusCode_isLocation(ms_s32 statuscode)
{
	return ms_range(statuscode, 300, 400)  ? ms_true: ms_false;
}
ms_bool msptc_api_statusCode_isOK(ms_s32 statuscode)
{
	return (NETSTATE_CODE_OK==statuscode||206==statuscode) ? ms_true: ms_false;
}
ms_void msptc_api_replay(ms_string protocol,char *outbuf,ms_u32 statuscode,ms_string pexinfo,ms_bool flag_token)
{
	ms_byte tbuf[2048]={0};
	ms_memset(outbuf, 0, ms_buflen(outbuf));
	if(ms_null==protocol || 0==ms_buflen(protocol)){
		ms_strcats(tbuf, outbuf, "%s %d %s\r\n", MSPTC_VERSION_HTTP,statuscode,netStateCode_string[statuscode]);
	}else{
		ms_strcats(tbuf, outbuf, "%s %d %s\r\n", protocol,statuscode,netStateCode_string[statuscode]);
	}
	ms_strcats(tbuf, outbuf, "%s", MSPTC_ACCESS_CONTROL);
	static ms_byte outStr[1024]={0};
	if(0==ms_buflen(outStr)){
		msmd_api_randomString(outStr);
	}
	ms_strcats(tbuf, outbuf,"Server: %s\r\n",outStr);
	ms_s08 strCurDTime[64]={0};
	ms_strcats(tbuf, outbuf, MSPTC_DATE_FORMAT, mstime_api_curDTime(mstime_fmt_datetime,strCurDTime));

	if(ms_null!=pexinfo&&ms_buflen(pexinfo)>0){
		ms_strcats(tbuf, outbuf, "%s", pexinfo);
	}

	//认证字符串，预留和干扰
	if(ms_true==flag_token){	
		char AuthentString[256] = {0};
		ms_string msptc_basekey="msos@MSPROTOCOL&837611-546765121354321231545643513213243543512";
		msdenc_api_encStr2(AuthentString,msptc_basekey,outbuf,FLAG,ms_null);
		ms_strcats(tbuf, outbuf,"Token: %s\r\n",AuthentString);
	}
	ms_strcat(outbuf,"\r\n");
}
ms_void msptc_api_replayOk(ms_string protocol,char *outbuf,ms_bool flag_token)
{
	msptc_api_replay(protocol, outbuf, NETSTATE_CODE_OK,"Pragma: no-cache\r\n", flag_token);
}
ms_void msptc_api_replayContent(ms_string protocol,char *content,char *content_string,char *outbuf)
{
	ms_byte tbuf[2048]={0};
	ms_byte exinfo[2048]={0};
	ms_strcats(tbuf,exinfo,"Content-Type: %s\r\n",content_string);
	ms_strcats(tbuf, exinfo,"Content-Length: %d\r\n",ms_strlen(content));
	msptc_api_replay(protocol, outbuf, NETSTATE_CODE_OK,exinfo,ms_true);
	ms_strcat(outbuf, content);
}

void msptc_api_replayMovedTemporarily(WEBREQUESTContext * prequest_ctt,
	ms_string location_url,char *outbuf)
{
	ms_byte tbuf[2048]={0};
	ms_byte exinfo[2048]={0};
	ms_strcats(tbuf, exinfo,"Location: %s\r\n",location_url);
	if(msstr_api_isCasestr(prequest_ctt->protocol, "RTSP")){
		ms_strcats(tbuf, exinfo, "CSeq: %s\r\n", prequest_ctt->extern_data.rtsp_rd.CSeq);
	}else{
		ms_strcat(exinfo,"Pragma: no-cache\r\n");
	}
	msptc_api_replay(prequest_ctt->protocol, outbuf, NETSTATE_CODE_MOVED_TEMPORARILY, exinfo,ms_true);
}
ms_void msptc_api_replayBusy(char *outbuf,int cur_connect,int max_connect)
{
	char tbuf[1024]={0};
	if(0==cur_connect
		||0==max_connect){
		msprotocol_api_replay_desinfo(MSPTC_VERSION_HTTP,outbuf,NETSTATE_CODE_SERVICE,tbuf,
			"%s","Server is busy and is temporarily inaccessible");
	}else{
		msprotocol_api_replay_desinfo(MSPTC_VERSION_HTTP,outbuf,NETSTATE_CODE_SERVICE,tbuf, 
			"Server is busy and is temporarily inaccessible."
			"The maximum number of services is %u, and the current service number is %u",
			max_connect, cur_connect);
	}
}
ms_void msptc_api_printStatusCode(int statuscode)
{
	if(statuscode<NETSTATE_CODE_MAX && statuscode>0){
		ms_verbose("RTSP STATUS:(code:%d)%s",statuscode,netStateCode_string[statuscode]);
	}else{
		ms_waring(" RTSP STATUS:Unknow status code:%d",statuscode);
	}
}
ms_s64 msptc_api_getVodSize(ms_string ms_in url)
{
extern URLProtocol ffurl_http_protocol;
	URLContext temp_tcc;
	memset(&temp_tcc,0, sizeof(URLContext));
	ms_strcpy(temp_tcc.url, url );
	ms_s32 ret=ffurl_http_protocol.url_open(&temp_tcc);
	HTTPContext * http_ctt=(HTTPContext *)temp_tcc.priv_data;
	ms_s32 size=http_ctt->content_len;
	ffurl_http_protocol.url_close(&temp_tcc);
	return size;
}
void msptc_api_urlSplit_urlinfo(URLInfo *purl_info,ms_string url)
{
	ms_verbose("url:%s", url);
	msstr_api_urlSplit(purl_info->ptcName, (ms_bufsize(purl_info->ptcName)), 
		purl_info->authorization, (ms_bufsize(purl_info->authorization)), 
		purl_info->hostname, (ms_bufsize(purl_info->hostname)), 
		&(purl_info->port),  
		purl_info->path, (ms_bufsize(purl_info->path)),  
		&(purl_info->flag_ipv6), 
		url);
	ms_verbose("hostname:%s", purl_info->hostname);
	//如果没有获取到协议名称，那么可能是文件或者目录
	if(0==ms_buflen(purl_info->ptcName)&&ms_strncmp_seq(url, "/")){
		ms_strcpy(purl_info->ptcName, msptc_api_getPtcName(msptc_file))
	}

}
void msptc_api_urlSplit_urlctt(URLContext *s)
{
	msptc_api_urlSplit_urlinfo(&s->url_info, s->url);
	//如果没有获取到协议名称，那么可能是文件或者目录
	if(0==ms_buflen(s->url_info.ptcName)&&ms_strncmp_seq(s->url, "/")){
		ms_strcpy(s->url_info.ptcName, msptc_api_getPtcName(msptc_file))
	}
}
ms_string msptc_api_getName(ms_u08 ptcindex)
{
	return msptcName_string[ptcindex];
}

ms_bool msptc_api_parseSdp(ms_string sdpfile)
{
#define sdp_get_content(tbuf,str_item) \
	if(msstr_api_isCasestr(tbuf, str_item) !=0){ms_verbose("%s",tbuf);}
	
	char *p =sdpfile;	
	char tbuf[256]={0};
	ms_s32 num_trackid=0;
	while(0!=*p){
		msstr_api_getLine(tbuf, sizeof(tbuf), (const char **)&p);
		sdp_get_content(tbuf, "v=")
		else sdp_get_content(tbuf, "o=")
		else sdp_get_content(tbuf, "s=")
		else sdp_get_content(tbuf, "c=")
		else sdp_get_content(tbuf, "t=")
		else sdp_get_content(tbuf, "a=tool")
		else if(msstr_api_isCasestr(tbuf, "m=") !=0){
			ms_verbose("%s",tbuf);
			num_trackid+=1;
		}
		else sdp_get_content(tbuf, "b=")
		else sdp_get_content(tbuf, "a=rtpmap")
		else sdp_get_content(tbuf, "a=fmtp")
		else sdp_get_content(tbuf, "a=control")
	}
	return (1!=num_trackid) ? ms_false : ms_true;
}

ms_bool msptc_api_checkUrl(ms_cstring     ms_in url)
{
	URLInfo url_info;
	ms_memset0(&url_info, ms_bufsize(URLInfo));
	msptc_api_urlSplit_urlinfo(&url_info, (ms_string)url);
	//ms_debug("protocol_name-%s, authorization-%s,hostname-%s, prot-%d,path-%s,url-%s",protocol_name, authorization,hostname, prot,path,url);
#define PRL_ERR_ITEM_NOHOST(ptl_name) \
	if(ms_strncmp_seq(url, ptl_name)&&(ms_strncmp_neq(ptl_name,url,ms_strlen(ptl_name)))){ \
		ms_errRet(ms_false,"url:%s (%s) is error  %d-%d",url,ptl_name, \
			ms_strncmp_seq(url, ptl_name), \
			(ms_strncmp_sneq(ptl_name,url))); \
	}
#define PRL_ERR_ITEM(ptl_name) \
	if(ms_strncmp_seq(url, ptl_name) \
		&&((ms_strncmp_neq(ptl_name,url,ms_strlen(ptl_name))) || !ms_strlen(url_info.hostname))){ \
		ms_errRet(ms_false,"url:%s (%s) is error  %d-%d-%d",url,ptl_name, \
			ms_strncmp_seq(url, ptl_name), \
			ms_strncmp_neq(ptl_name,url,ms_strlen(ptl_name)),!ms_strlen(url_info.hostname)); \
	}
//通用校验		
	if(ms_strlen(url_info.ptcName)){
		int index=0;
		for(index=0;index<ms_strlen(url_info.ptcName);index++){
			if(url_info.ptcName[index]!=':'
				&&url_info.ptcName[index]!='/' //文件目录或文件路径
				&&!ms_range(url_info.ptcName[index], 'a', 'z')
				&&!ms_range(url_info.ptcName[index], 'A', 'Z')){
				ms_errRet(ms_false,"protocol_name:%s error (%c)",url_info.ptcName,url_info.ptcName[index]);
			}
		}
	}else{
		return ms_true;
	}
//只校验协议名称
	PRL_ERR_ITEM_NOHOST("file"); 
//校验协议名称，且必须有主机IP
	PRL_ERR_ITEM("http");  
	PRL_ERR_ITEM("rtmp");
	PRL_ERR_ITEM("rtsp");
	return ms_true;
}

ms_bool msptc_api_isUrl(ms_cstring  ms_in url)
{
	ENUPROTOCOLIndex ptl_index=msptc_api_getPtcindex((char *)url,ms_null,ms_false);
	if(msptc_file==ptl_index
		||msptc_udp==ptl_index
		||msptc_rtp==ptl_index
		||msptc_rtmp==ptl_index
		||msptc_hls==ptl_index
		||msptc_msoshls_tssl==ptl_index
		||msptc_msoshls==ptl_index
		||msptc_https==ptl_index
		||msptc_http==ptl_index
		||msptc_dash==ptl_index	
		||msptc_https_vod==ptl_index
		||msptc_http_vod==ptl_index
		||msptc_ws==ptl_index
		||msptc_rtsp==ptl_index
		||msptc_tcp==ptl_index
		||msptc_srt==ptl_index
		||msptc_none==ptl_index
		||msptc_raw==ptl_index){
		return ms_true;
	}else{
		return ms_false;
	}
}
/*获取RTP的负载信息*/
RTPPAYLOADTYPEContext *msptc_api_getRtpPTInfo(RTPPAYLOADType pt)
{
	RTPPAYLOADTYPEContext *pRtpPayloadType_ctt=ms_null;
	ms_s32 index=0;
	 for (index = 0; rtpPayloadType_list[index].pt >= 0; index++){
		pRtpPayloadType_ctt=&rtpPayloadType_list[index];
		if(pt==pRtpPayloadType_ctt->pt){
			return pRtpPayloadType_ctt;
		}
	}
	return pRtpPayloadType_ctt;
}


ms_void msptc_api_info(ms_string ms_out pbuf)
{
#if defined OS_LINUX_SOC  
	#if defined OS_PLATFORM_ARM64  
		strcat(pbuf, "linux_aarch64");
	#elif defined OS_PLATFORM_ARMV7L
		strcat(pbuf, "linux_armv7l");
	#else
		strcat(pbuf, "linux_soc");
	#endif
#else
	#if defined OS_PLATFORM_ARM64  
		strcat(pbuf, "unlinux_aarch64");
	#elif defined OS_PLATFORM_ARMV7L
		strcat(pbuf, "unlinux_armv7l");
	#else
		strcat(pbuf, "unlinux_soc");
	#endif
#endif
	strcat(pbuf, "|raw");
	strcat(pbuf, "|udp");
	strcat(pbuf, "|udplite");
	strcat(pbuf, "|tcp");
#if defined CONFIG_MSPROTOCOL_TSSL 
	strcat(pbuf, "|tssl");
#else
	strcat(pbuf, "|no-tssl");
#endif
#if defined CONFIG_MSPROTOCOL_SRT 
	strcat(pbuf, "|srt");
#else
	strcat(pbuf, "|no-srt");
#endif
	strcat(pbuf, "|rtp");
	strcat(pbuf, "|rtsp");
	strcat(pbuf, "|http");
	strcat(pbuf, "|hls");
	strcat(pbuf, "|file");
	strcat(pbuf, "|pipe");
	strcat(pbuf, "|none");
#ifdef CONFIG_MSPROTOCOL_LIBRTMP
	strcat(pbuf, "|rtmp");
	strcat(pbuf, "|rtmpt");
	strcat(pbuf, "|rtmpe");
	strcat(pbuf, "|rtmpte");
	strcat(pbuf, "|rtmps");
#else
	strcat(pbuf, "|no-librtmp");
#endif
#ifdef CONFIG_MSPROTOCOL_MSAV
	strcat(pbuf, "|msav");
#else
	strcat(pbuf, "|no-msav");
#endif
}

ms_string msptc_api_version(ms_void)
{
	return "01.04.18";
}
#undef MSPROTOCOL_C
